// var bar = {
//     Lname: '老哥',
//     printName:function () {
//         console.log(Lname);
//     }
// }

// function foo() {
//     let Lname = '老大'
//     return bar.printName
// }

// let Lname = '胖子'
// let _printName = foo()
// _printName() // 胖子
// bar.printName() // 全局下调用


// function foo() {
//     console.log(this.a);
// }

// var a = 1
// foo()

let obj = {
    name: '曹哥'
}

function foo(a, b) {
    console.log(this.name);
    console.log(a + b);
}



Function.prototype._call = function (context = window) {
    if (typeof this != 'function' || this == null) {
        throw new Error('error')
    }

    let argu = [...arguments].slice(1)
    context.fn = this
    let result = context.fn(...argu)
    delete context.fn
    return result
}

Function.prototype._apply = function (context = window) {
    if (typeof this != 'function' || this == null) {
        throw new Error('error')
    }
    let argu = [...arguments].flat(Infinity).splice(1)
    // console.log(argu, arguments);
    context.fn = this
    let result = context.fn(...argu)
    delete context.fn
    return result
}

Function.prototype._bind = function (context) {
    if (typeof this != 'function' || this == null) {
        throw new Error('error')
    }
    context = context || window
    let argu = [...arguments].slice(1)
    let self = this
    return function F() {
        if(this instanceof F) {
            return new self()
        }
        return self._apply(context, argu.concat(...arguments))
    }
}
let fn = foo._bind(obj)
fn(5, 3)
foo._bind(obj)(1, 2)

foo._apply(obj, [1, 2])